using UnityEngine;

/**
 在ComputeShader, cs, RenderShader中都定义了ParticleData的struct, 包含Pos和Color.
 使用ComputeBuffer传递自定义数据结构, 注意计算buffer size.
 */

/// <summary>
/// Demo-2. 使用ComputeShader驱动粒子.
/// </summary>
public class ParticleRunner : MonoBehaviour
{
    public struct ParticleData
    {
        public Vector3 pos;//等价于float3
        public Color color;//等价于float4

        //内存占用大小
        public static int Size()
        {
            /* 
            //只有在unsafe情况下才能使用sizeof.
            unsafe
            {
                return sizeof(ParticleData);
            }
            */

            //float3 + float4, 相当于7个float, 每个float是4byte, 所以size是4*7=28
            return 28;
        }
    }

    public ComputeShader shader;
    public int ParticleCount = 256;
    public float Speed = 0.005f;
    public Material mat;

    private ComputeBuffer buffer;
    private int kernelId;

    private void OnEnable()
    {
        //初始化Compute buffer
        buffer = new ComputeBuffer(ParticleCount, ParticleData.Size());
        var particleArray = new ParticleData[ParticleCount];
        buffer.SetData(particleArray);

        //获取核函数Id
        kernelId = shader.FindKernel("UpdateParticle");
    }

    private void OnDisable()
    {
        //释放buffer.
        buffer.Release();
        buffer = null;
    }

    private void Update()
    {
        //computeShader中的ParticleBuffer是RWStructuredBuffer, 使用SetBuffer传递该类型参数.
        shader.SetBuffer(kernelId, "ParticleBuffer", buffer);

        //传递两个float参数
        shader.SetFloat("Time", Time.time);
        shader.SetFloat("Speed", Speed);

        //shader计算.
        shader.Dispatch(kernelId, ParticleCount / 1000, 1, 1);

        //渲染材质获取计算后的buffer. 此时的pos和color都以计算完毕
        //ComputeShader的同步是怎样的?
        mat.SetBuffer("ParticleBuffer", buffer);
    }

    private void OnRenderObject()
    {
        //直接使用Point根据Vertex的Pos和Color进行渲染.
        mat.SetPass(0);
        Graphics.DrawProceduralNow(MeshTopology.Points, ParticleCount);
    }
}